/**
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.api.adwords.starterkit.examples.enhancedads;

import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.api.adwords.starterkit.utils.JSONUtils;
import com.google.api.adwords.starterkit.utils.SettingsException;

public class CollectionItem {
  private String tag;
  private CollectionRule rule;
  private String ruleValue;
  private String value;
  private Currency currency;
  private boolean hidden;
  
  private static final Logger log = Logger.getLogger("StarterKit");
  
  public CollectionItem(String tag, CollectionRule rule, String ruleValue, 
      String value, Currency currency, boolean hidden) {
    this.tag = tag;
    this.rule = rule;
    this.currency = currency;
    setRuleValue(ruleValue);    
    setValue(value);
    this.hidden = hidden;
  }
  
  public CollectionItem(String tag, String value, Currency currency, 
      boolean hidden) {
    this.tag = tag;
    this.rule = null;
    this.ruleValue = null;
    this.currency = currency;
    setValue(value);
    this.hidden = hidden;
  }
  
  public boolean isHidden() {
    return hidden;
  }
  
  public void setHidden(boolean hidden) {
    this.hidden = hidden;
  }
  
  public void setValue(String value) {
    if (value == null) {
      this.value = null;
      return;
    }
    if (rule != null) {
      String iValue = value;
      // remove Currency format and set it format to standard float
      if (currency.isCurrency(iValue)) {
        Float fValue = currency.toFloat(iValue);
        iValue = fValue.toString();
      }
      if (isValid(iValue)) {
        this.value = value;
      } else {
        value = null;
      }
    } else {
      this.value = value; 
    }
  }
  
  public static CollectionItem fromJSON(Object jsonObject, Currency currency) 
      throws JSONException {
    String content = "";
    String rule = "";
    String ruleValue = "";
    CollectionRule collectionRule = null;
    boolean hidden = false;
    // is the Tag a simple tag without any rule on it?
    if (jsonObject.getClass().getSimpleName().equals("String")) {
      content = (String) jsonObject;
      rule = null;
      ruleValue = null;
    } else {
      JSONObject jsonTag = (JSONObject) jsonObject;
      content = jsonTag.getString("content");
      
      // capture the rule defined at the Tag
      rule = JSONUtils
          .getJSONString(jsonTag, "rule", null);
      ruleValue = JSONUtils
          .getJSONString(jsonTag, "value", null);
      
      // identify if the Tag is visible or not 
      hidden = JSONUtils
          .getJSONBoolean(jsonTag, "hidden", false);
      
      try {
        collectionRule = CollectionRule.fromString(rule);
      } catch (SettingsException e) {
        log.error(e.getMessage());
      }
    }

    return new CollectionItem(content, 
        collectionRule, ruleValue, null, currency, hidden); 
  }
  
  public String getValue() {
    return value;
  }
  
  public void setTag(String tag) {
    this.tag = tag;
  }
  
  public String getTag() {
    return tag;
  }
  
  public void setRule(CollectionRule rule) {
    this.rule = rule;
  }
  
  public CollectionRule getRule() {
    return rule;
  }
  
  public void setRuleValue(String value) {
    if (currency.isCurrency(value)) {
      Float fValue = currency.toFloat(value);
      this.ruleValue  = fValue.toString();
    } else {    
      this.ruleValue = value;
    }
  }
  
  public String getRuleValue() {
    return ruleValue;
  }
  
  public boolean isValid(String value) {
    if (rule == CollectionRule.CONTAINS) {
      return isValid(value, ruleValue);
    } else if ((isInteger(value) || isFloat(value)) 
        && (isInteger(ruleValue) || isFloat(ruleValue))) {
        float fValue = Float.valueOf(value);
        float fRuleValue = Float.valueOf(ruleValue);
        return isValid(fValue, fRuleValue);
    } else {
      return isValid(value, ruleValue);
    }       
  }
  
  private boolean isValid(String value, String ruleValue) {
    value = value.toLowerCase();
    ruleValue = ruleValue.toLowerCase();
    if (rule == CollectionRule.EQUALS) {
      return value.equals(ruleValue);
    } else if (rule == CollectionRule.CONTAINS) {
      return value.contains(ruleValue);
    }   
    return false;
  }
    
  private boolean isValid(float value, float ruleValue) {
    if (rule == CollectionRule.EQUALS) {
      return value == ruleValue;
    } else if (rule == CollectionRule.GREATER_THAN) {
      return value > ruleValue;
    } else if (rule == CollectionRule.GREATER_EQUAL_THAN) {
      return value >= ruleValue;
    } else if (rule == CollectionRule.LOWER_THAN) {
      return value < ruleValue;
    } else if (rule == CollectionRule.LOWER_EQUAL_THAN) {
      return value <= ruleValue;
    }
    return false;
  }
  
  private boolean isInteger(String value) {
    try {
      Integer.valueOf(value);
      return true;
    } catch (NumberFormatException e) {
      return false;
    }
  }
  
  private boolean isFloat(String value) {
    try {
      Float.valueOf(value);
      return true;
    } catch (NumberFormatException e) {
      return false;
    }
  }  
}